package com.example.blueconn.conn;

import android.util.Log;

import com.example.blueconn.BuildConfig;
import com.example.blueconn.Constant;
import com.example.blueconn.manager.DataMgr;
import com.example.blueconn.manager.PreferenceManager;
import com.example.blueconn.utils.DataUtils;
import com.example.blueconn.utils.ThreadPoolUtils;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

public class TcpClient {
    private static final String TAG = "TcpClient";

    private String remoteIp;
    private int remotePort;
    private final Socket socket;

    public byte[] readData;
    private DataOutputStream dataOutputStream;
    private InputStream inputStream;
    private StringBuilder strBuilder = new StringBuilder();
    private byte[] bytes = new byte[1024];

    private boolean acceptWorkRun = false;

    private static TcpClient tcpClient;

    public TcpClient(String ip, int port) {
        this.remoteIp = ip;
        this.remotePort = port;

        socket = new Socket();
        try {
            socket.setTcpNoDelay(false);
            socket.setKeepAlive(true);
            //读取数据超时，默认0，无限超时。单位ms
//            socket.setSoTimeout(5000);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    public static TcpClient getInstance() {
        if (tcpClient == null) {
            String ip = PreferenceManager.getInstance().getString(Constant.WIFI_HOST_KEY, Constant.WIFI_HOST_DEFAULT_VALUE);
            int port = PreferenceManager.getInstance().getInt(Constant.WIFI_PORT_KEY, Constant.WIFI_PORT_DEFAULT_VALUE);
            tcpClient = new TcpClient(ip, port);
        }
        return tcpClient;
    }

    public void connect() {
        ThreadPoolUtils.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    InetAddress inetAddress = InetAddress.getByName(remoteIp);
                    socket.connect(new InetSocketAddress(inetAddress,remotePort),10000);
                    socket.setSendBufferSize(3000);
                    socket.setReceiveBufferSize(3000);
                    socket.setTcpNoDelay(false);
                    socket.setKeepAlive(true);
                    startRead();
                    Log.i(TAG, "run: 连接成功！");
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void read() {
        if (!BuildConfig.DEBUG) {
            try {
                if (inputStream == null && socket != null) {
                    inputStream = socket.getInputStream();
                }
                int len = 0;
                //清理stringBuilder
                strBuilder.setLength(0);
                len = inputStream.read(bytes);
                if (len != -1) {
                    strBuilder.append(DataUtils.encodeHexStr(bytes, len));
                }
                String readString = strBuilder.toString();
                Log.i(TAG, "read: " + readString);
                DataMgr.getInstance().postRawData(readString);
            } catch (IOException e) {
                Log.i(TAG, "read: " + e);
                e.printStackTrace();
            }
        }
    }

    public void write(final byte[] data) {
        ThreadPoolUtils.submit(new Runnable() {
            @Override
            public void run() {
                if (socket != null) {
                    try {
                        if (dataOutputStream == null) {
                            if (!socket.isConnected()) {
                                connect();
                            }
                            OutputStream outputStream = socket.getOutputStream();
                            dataOutputStream = new DataOutputStream(outputStream);
                        }
                        dataOutputStream.write(data);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

    }

    public void write(String data) {
        byte[] bt = DataUtils.hexToBytes(data);
        write(bt);
    }

    public void startRead() {
        if (socket != null && !socket.isClosed() && !socket.isConnected()) {
            Log.i(TAG, "startRead: connect");
            connect();
        } else {
            Log.i(TAG, "startRead: readData");
            acceptWorkRun = true;
            ThreadPoolUtils.submit(new AcceptWorkRunnable());
        }
    }

    public void close() {
        acceptWorkRun = false;
        try {
            if (dataOutputStream != null) {
                dataOutputStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void postData() {
        acceptWorkRun = true;
        ThreadPoolUtils.submit(new AcceptWorkRunnable());
    }

    //读取数据的工作线程
    public class AcceptWorkRunnable implements Runnable {

        @Override
        public void run() {
            while (acceptWorkRun) {
                if (BuildConfig.DEBUG) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                read();
            }
        }
    }
}
